home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / net / RCS / res_query.c,v < prev    next >
Text File  |  1988-07-29  |  7KB  |  295 lines

  1. head     1.2;
  2. access   ;
  3. symbols  ;
  4. locks    ; strict;
  5. comment  @ * @;
  6.  
  7.  
  8. 1.2
  9. date     88.07.29.16.59.59;  author ouster;  state Exp;
  10. branches ;
  11. next     1.1;
  12.  
  13. 1.1
  14. date     88.06.20.09.57.20;  author ouster;  state Exp;
  15. branches ;
  16. next     ;
  17.  
  18.  
  19. desc
  20. @@
  21.  
  22.  
  23. 1.2
  24. log
  25. @Lint.
  26. @
  27. text
  28. @/*
  29.  * Copyright (c) 1988 Regents of the University of California.
  30.  * All rights reserved.
  31.  *
  32.  * Redistribution and use in source and binary forms are permitted
  33.  * provided that this notice is preserved and that due credit is given
  34.  * to the University of California at Berkeley. The name of the University
  35.  * may not be used to endorse or promote products derived from this
  36.  * software without specific prior written permission. This software
  37.  * is provided ``as is'' without express or implied warranty.
  38.  */
  39.  
  40. #if defined(LIBC_SCCS) && !defined(lint)
  41. static char sccsid[] = "@@(#)res_query.c    5.4 (Berkeley) 4/21/88";
  42. #endif /* LIBC_SCCS and not lint */
  43.  
  44. #include <sys/param.h>
  45. #include <sys/socket.h>
  46. #include <netinet/in.h>
  47. #include <ctype.h>
  48. #include <netdb.h>
  49. #include <stdio.h>
  50. #include <errno.h>
  51. #include <strings.h>
  52. #include <arpa/inet.h>
  53. #include <arpa/nameser.h>
  54. #include <resolv.h>
  55.  
  56. #if PACKETSZ > 1024
  57. #define MAXPACKET    PACKETSZ
  58. #else
  59. #define MAXPACKET    1024
  60. #endif
  61.  
  62. extern int errno;
  63. int h_errno;
  64.  
  65. /*
  66.  * Formulate a normal query, send, and await answer.
  67.  * Returned answer is placed in supplied buffer "answer".
  68.  * Perform preliminary check of answer, returning success only
  69.  * if no error is indicated and the answer count is nonzero.
  70.  * Return the size of the response on success, -1 on error.
  71.  * Error number is left in h_errno.
  72.  * Caller must parse answer and determine whether it answers the question.
  73.  */
  74. res_query(name, class, type, answer, anslen)
  75.     char *name;        /* domain name */
  76.     int class, type;    /* class and type of query */
  77.     u_char *answer;        /* buffer to put answer */
  78.     int anslen;        /* size of answer buffer */
  79. {
  80.     char buf[MAXPACKET];
  81.     HEADER *hp;
  82.     int n;
  83.  
  84.     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  85.         return (-1);
  86. #ifdef DEBUG
  87.     if (_res.options & RES_DEBUG)
  88.         printf("res_query(%s, %d, %d)\n", name, class, type);
  89. #endif
  90.     n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0,
  91.         (struct rrec *) NULL, buf, sizeof(buf));
  92.  
  93.     if (n <= 0) {
  94. #ifdef DEBUG
  95.         if (_res.options & RES_DEBUG)
  96.             printf("res_query: mkquery failed\n");
  97. #endif
  98.         h_errno = NO_RECOVERY;
  99.         return (n);
  100.     }
  101.     n = res_send(buf, n, (char *) answer, anslen);
  102.     if (n < 0) {
  103. #ifdef DEBUG
  104.         if (_res.options & RES_DEBUG)
  105.             printf("res_query: send error\n");
  106. #endif
  107.         h_errno = TRY_AGAIN;
  108.         return(n);
  109.     }
  110.  
  111.     hp = (HEADER *) answer;
  112.     if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
  113. #ifdef DEBUG
  114.         if (_res.options & RES_DEBUG)
  115.             printf("rcode = %d, ancount=%d\n", hp->rcode,
  116.                 ntohs(hp->ancount));
  117. #endif
  118.         switch (hp->rcode) {
  119.             case NXDOMAIN:
  120.                 h_errno = HOST_NOT_FOUND;
  121.                 break;
  122.             case SERVFAIL:
  123.                 h_errno = TRY_AGAIN;
  124.                 break;
  125.             case NOERROR:
  126.                 h_errno = NO_DATA;
  127.                 break;
  128.             case FORMERR:
  129.             case NOTIMP:
  130.             case REFUSED:
  131.             default:
  132.                 h_errno = NO_RECOVERY;
  133.                 break;
  134.         }
  135.         return (-1);
  136.     }
  137.     return(n);
  138. }
  139.  
  140. /*
  141.  * Formulate a normal query, send, and retrieve answer in supplied buffer.
  142.  * Return the size of the response on success, -1 on error.
  143.  * If enabled, implement search rules until answer or unrecoverable failure
  144.  * is detected.  Error number is left in h_errno.
  145.  * Only useful for queries in the same name hierarchy as the local host
  146.  * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
  147.  */
  148. res_search(name, class, type, answer, anslen)
  149.     char *name;        /* domain name */
  150.     int class, type;    /* class and type of query */
  151.     u_char *answer;        /* buffer to put answer */
  152.     int anslen;        /* size of answer */
  153. {
  154.     register char *cp, **domain;
  155.     int n, ret, got_nodata = 0;
  156.     char *hostalias();
  157.  
  158.     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  159.         return (-1);
  160.  
  161.     errno = 0;
  162.     h_errno = HOST_NOT_FOUND;        /* default, if we never query */
  163.     for (cp = name, n = 0; *cp; cp++)
  164.         if (*cp == '.')
  165.             n++;
  166.     if (n == 0 && (cp = hostalias(name)))
  167.         return (res_query(cp, class, type, answer, anslen));
  168.  
  169.     if ((n == 0 || *--cp != '.') && (_res.options & RES_DEFNAMES))
  170.         for (domain = _res.dnsrch; *domain; domain++) {
  171.         ret = res_querydomain(name, *domain, class, type,
  172.             answer, anslen);
  173.         if (ret > 0)
  174.             return (ret);
  175.         /*
  176.          * If no server present, give up.
  177.          * If name isn't found in this domain,
  178.          * keep trying higher domains in the search list
  179.          * (if that's enabled).
  180.          * On a NO_DATA error, keep trying, otherwise
  181.          * a wildcard entry of another type could keep us
  182.          * from finding this entry higher in the domain.
  183.          * If we get some other error (non-authoritative negative
  184.          * answer or server failure), then stop searching up,
  185.          * but try the input name below in case it's fully-qualified.
  186.          */
  187.         if (errno == ECONNREFUSED) {
  188.             h_errno = TRY_AGAIN;
  189.             return (-1);
  190.         }
  191.         if (h_errno == NO_DATA)
  192.             got_nodata++;
  193.         if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
  194.             (_res.options & RES_DNSRCH) == 0)
  195.             break;
  196.     }
  197.     /*
  198.      * If the search/default failed, try the name as fully-qualified,
  199.      * but only if it contained at least one dot (even trailing).
  200.      */
  201.     if (n)
  202.         return (res_querydomain(name, (char *)NULL, class, type,
  203.             answer, anslen));
  204.     if (got_nodata)
  205.         h_errno = NO_DATA;
  206.     return (-1);
  207. }
  208.  
  209. /*
  210.  * Perform a call on res_query on the concatenation of name and domain,
  211.  * removing a trailing dot from name if domain is NULL.
  212.  */
  213. res_querydomain(name, domain, class, type, answer, anslen)
  214.     char *name, *domain;
  215.     int class, type;    /* class and type of query */
  216.     u_char *answer;        /* buffer to put answer */
  217.     int anslen;        /* size of answer */
  218. {
  219.     char nbuf[2*MAXDNAME+2];
  220.     char *longname = nbuf;
  221.     int n;
  222.  
  223. #ifdef DEBUG
  224.     if (_res.options & RES_DEBUG)
  225.         printf("res_querydomain(%s, %s, %d, %d)\n",
  226.             name, domain, class, type);
  227. #endif
  228.     if (domain == NULL) {
  229.         /*
  230.          * Check for trailing '.';
  231.          * copy without '.' if present.
  232.          */
  233.         n = strlen(name) - 1;
  234.         if (name[n] == '.' && n < sizeof(nbuf) - 1) {
  235.             bcopy(name, nbuf, n);
  236.             nbuf[n] = '\0';
  237.         } else
  238.             longname = name;
  239.     } else
  240.         (void)sprintf(nbuf, "%.*s.%.*s",
  241.             MAXDNAME, name, MAXDNAME, domain);
  242.  
  243.     return (res_query(longname, class, type, answer, anslen));
  244. }
  245.  
  246. char *
  247. hostalias(name)
  248.     register char *name;
  249. {
  250.     register char *C1, *C2;
  251.     FILE *fp;
  252.     char *file, *getenv(), *strcpy(), *strncpy();
  253.     char buf[BUFSIZ];
  254.     static char abuf[MAXDNAME];
  255.  
  256.     file = getenv("HOSTALIASES");
  257.     if (file == NULL || (fp = fopen(file, "r")) == NULL)
  258.         return (NULL);
  259.     buf[sizeof(buf) - 1] = '\0';
  260.     while (fgets(buf, sizeof(buf), fp)) {
  261.         for (C1 = buf; *C1 && !isspace(*C1); ++C1);
  262.         if (!*C1)
  263.             break;
  264.         *C1 = '\0';
  265.         if (!strcasecmp(buf, name)) {
  266.             while (isspace(*++C1));
  267.             if (!*C1)
  268.                 break;
  269.             for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
  270.             abuf[sizeof(abuf) - 1] = *C2 = '\0';
  271.             (void)strncpy(abuf, C1, sizeof(abuf) - 1);
  272.             fclose(fp);
  273.             return (abuf);
  274.         }
  275.     }
  276.     fclose(fp);
  277.     return (NULL);
  278. }
  279. @
  280.  
  281.  
  282. 1.1
  283. log
  284. @Initial revision
  285. @
  286. text
  287. @d63 2
  288. a64 2
  289.     n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL,
  290.         buf, sizeof(buf));
  291. d74 1
  292. a74 1
  293.     n = res_send(buf, n, answer, anslen);
  294. @
  295.